package com.browsesoft;

import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

public class ExtendElement {
	/**
	 * 根据属性和属性值在需要处理的元素中查找元素
	 * 
	 * @param e
	 *            元素
	 * @param name
	 *            属性名
	 * @param value
	 *            属性值
	 * @return 元素列表
	 */
	public static LinkedList findElements(Element e, String name, String value) {
		Hashtable ht = new Hashtable();
		ht.put(name, value);
		return findElements(e, ht);
	}

	/**
	 * 设置select的选择项
	 */
	public static void setSelectValue(Iterator options, Element dealElement) {
		ExtendElement.removeChilds(dealElement);
		while (options.hasNext()) {
			// 构造选择项
			Element element = dealElement.getOwnerDocument().createElement(
					"option");
			dealElement.appendChild(element);
			// 设置选择项内容
			String context = options.next().toString();
			Text text = dealElement.getOwnerDocument().createTextNode(context);
			element.appendChild(text);
		}
	}

	/**
	 * 设置文本框内容
	 * 
	 * @param dealElement
	 *            要处理的元素
	 * @param objectValue
	 *            要处理的元素值
	 */
	public static void setTextareaValue(Element dealElement, String objectValue) {
		// 去回车和换行
		objectValue = objectValue.replaceAll("\n", "");
		ExtendElement.removeChilds(dealElement);
		// 插入文本内容
		dealElement.appendChild(dealElement.getOwnerDocument().createTextNode(
				objectValue));
	}

	public static LinkedList findElementsByTagName(Element e, String tagName,
			String name, String value) {
		LinkedList list = findElements(e, name, value);
		LinkedList r = new LinkedList();
		for (int i = 0; i < list.size(); i++) {
			Element element = (Element) list.get(i);
			if (element.getTagName().equals(tagName)) {
				r.add(element);
			}
		}
		return r;
	}

	/**
	 * 根据属性和属性值对条件找某元素下满足条件的所有后代元素列表
	 * 
	 * @param propertyAndValue
	 *            属性和属性值对表示的条件
	 * @return 元素列表
	 */
	public static LinkedList findElements(Element parent,
			Hashtable propertyAndValue) {
		LinkedList ret = new LinkedList();
		// 在子中找
		for (int i = 0; i < parent.getChildNodes().getLength(); i++) {
			Node node = parent.getChildNodes().item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				Element enode = (Element) node;
				// 从哈西表中取属性和属性值
				Enumeration en = propertyAndValue.keys();
				int equal = 0;
				while (en.hasMoreElements()) {
					// 得到字段名和字段值
					Object key = en.nextElement();
					String propertyName = key.toString();
					String propertyValue = propertyAndValue.get(key).toString();
					// 进行比较
					String value = enode.getAttribute(propertyName);
					if (!value.toLowerCase()
							.equals(propertyValue.toLowerCase())) {
						break;
					}
					equal++;
				}
				if (equal == propertyAndValue.size()) {
					ret.add(enode);
				}
				ret.addAll(findElements(enode, propertyAndValue));
			}
		}
		return ret;
	}

	/**
	 * 得到元素后代中所有给定标记的元素列表，只找一层，找到了就不再找。
	 */
	public static List getElementByTagName(Element e, String name) {
		List result = new LinkedList();
		// 对于所有子
		NodeList nodes = e.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			// 如果不是元素
			if (!(node instanceof Element)) {
				// 继续
				continue;
			}
			// 如果与给定标记相同
			Element element = (Element) node;
			if (element.getTagName().equals(name)) {
				// 添加到结果中
				result.add(element);
			}
			// 否则
			else {
				// 继续找，把找到的结果添加到结果中
				result.addAll(getElementByTagName(element, name));
			}
		}
		return result;
	}

	/**
	 * 根据属性和属性值对条件找某元素下满足条件的所有后代元素列表，条件中的属性值为模糊查询
	 * 
	 * @param propertyAndValue
	 *            属性和属性值对表示的条件
	 * @return 元素列表
	 */
	public static LinkedList getElementsByInclude(Element parent,
			Hashtable propertyAndValue) {
		LinkedList ret = new LinkedList();
		// 在子中找
		for (int i = 0; i < parent.getChildNodes().getLength(); i++) {
			Node node = parent.getChildNodes().item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				Element enode = (Element) node;
				// 从哈西表中取属性和属性值
				Enumeration en = propertyAndValue.keys();
				int equal = 0;
				while (en.hasMoreElements()) {
					// 得到字段名和字段值
					Object key = en.nextElement();
					String propertyName = key.toString();
					String propertyValue = propertyAndValue.get(key).toString();
					// 进行比较
					String value = enode.getAttribute(propertyName);
					if (value.toLowerCase()
							.indexOf(propertyValue.toLowerCase()) == -1) {
						break;
					}
					equal++;
				}
				if (equal == propertyAndValue.size()) {
					ret.add(enode);
				}
				ret.addAll(findElements(enode, propertyAndValue));
			}
		}
		return ret;
	}

	/**
	 * 根据属性和属性值在需要处理的元素中查找元素，条件中的属性值为模糊查询
	 * 
	 * @param e
	 *            元素
	 * @param name
	 *            属性名
	 * @param value
	 *            属性值
	 * @return 元素列表
	 */
	public static LinkedList getElementsByInclude(Element e, String name,
			String value) {
		Hashtable ht = new Hashtable();
		ht.put(name, value);
		return getElementsByInclude(e, ht);
	}

	/**
	 * 替换元素中的第一个文本节点
	 * 
	 * @param e
	 *            元素
	 * @param text
	 *            新的文本内容
	 */
	public static void replaceElementContext(Element e, String text) {
		// 空元素不处理
		if (e == null) {
			return;
		}
		// 如果文本为空
		if (text == null) {
			// 转换成空串
			text = "";
		}
		// 创建文本节点
		Node node = e.getOwnerDocument().createTextNode(text);
		// 替换节点
		replaceElementContext(e, node);
	}

	/**
	 * 替换元素中的第一个文本节点
	 * 
	 * @param e
	 *            元素
	 */
	public static void replaceElementContext(Element e, Node newNode) {
		LinkedList ls = findElementContext(e);
		if (ls.size() > 0) {
			Text old = (Text) ls.get(0);
			if (old == null) {
				e.appendChild(newNode);
			} else {
				old.getParentNode().replaceChild(newNode, old);
			}
		} else {
			System.out.println("在" + e.toString()
					+ "元素中没有找到要替换的text元素,可能不能正常显示");
		}
	}

	/**
	 * 找到元素中的文本节点列表
	 * 
	 * @param node
	 *            节点
	 * @return 文本节点列表
	 */
	public static LinkedList findElementContext(Node node) {
		LinkedList v = new LinkedList();
		for (int i = 0; i < node.getChildNodes().getLength(); i++) {
			Node n = node.getChildNodes().item(i);
			if (n.getChildNodes().getLength() != 0) {
				v.addAll(findElementContext(n));
			}
			if (n.getNodeType() == Node.TEXT_NODE) {
				v.add(n);
			}
		}
		return v;
	}

	/**
	 * 读取元素e及其子元素下的要处理的元素，需要处理的元素拥有属性fieldType='typeName'
	 * 其中，typeName为该属性的数据库字段名，可以为空(fieldType='')，以表示不存入数据库中
	 * ，读出的元素以后可以使用findElement(attrName, attrValue)函数读出。
	 * 
	 * @param e
	 *            元素
	 */
	public static LinkedList findElementsOfAttr(Element e, String name) {
		LinkedList attrList = new LinkedList();
		for (int i = 0; i < e.getChildNodes().getLength(); i++) {
			Node ee = e.getChildNodes().item(i);
			if (ee.getNodeType() == Node.ELEMENT_NODE) {
				// 如果有fieldType属性，则是需要处理的字段
				if (((Element) ee).hasAttribute(name)) {
					attrList.addLast((Element) ee);
				}
				attrList.addAll(findElementsOfAttr((Element) ee, name));
			}
		}
		return attrList;
	}

	/**
	 * 从元素e中删除某一子结点元素下的所有子结点
	 * 
	 * @param e
	 *            元素
	 * @param tagName
	 *            要删除的子结点名
	 */
	public static void removeNodes(Element e, String tagName) {
		// 得到要删除的元素结点列表
		NodeList list = e.getElementsByTagName(tagName);
		// 如果存在该元素结点
		if (list.getLength() > 0) { // 得到该元素下的所有子结点列表
			Element ele = (Element) list.item(0);
			NodeList childlist = ele.getChildNodes();
			// 当子结点列表不为空时，删除该元素下所有子结点
			while (childlist.getLength() > 0) {
				Node node = childlist.item(0);
				ele.removeChild(node);
			}
		}
	}

	/**
	 * 删除元素下得标记元素
	 * 
	 */
	public static void removeNodesByTag(Element e, String tag) {
		// 得到要删除的元素结点列表
		NodeList list = e.getElementsByTagName(tag);
		// 如果存在该元素结点
		if (list.getLength() > 0) { // 得到该元素下的所有子结点列表
			Element ele = (Element) list.item(0);
			e.removeChild(ele);
		}
	}

	/**
	 * 删除元素所有子
	 * 
	 * @param e
	 */
	public static void removeChilds(Element e) {
		while (e.hasChildNodes()) {
			Node node = e.getFirstChild();
			node.getParentNode().removeChild(node);
		}
	}

	/**
	 * 
	 * @param e
	 * @param name
	 * @param value
	 */
	public static void removeChilds(Element e, String name, String value) {
		LinkedList ls = findElements(e, name, value);
		Iterator iter = ls.iterator();
		while (iter.hasNext()) {
			Element node = (Element) iter.next();
			removeChilds(node);
		}
	}

	/**
	 * 得到元素集合中每个元素的某个属性值
	 * 
	 * @param elems
	 *            所有元素
	 * @param attrName
	 *            属性名
	 */
	public static LinkedList findAttrOfElemnts(NodeList elems, String attrName) {
		LinkedList result = new LinkedList();
		// 得到所有元素名称
		for (int i = 0; i < elems.getLength(); i++) {
			// 得到每一个元素改项属性值
			Element oneElem = (Element) elems.item(i);
			result.add(oneElem.getAttribute(attrName));
		}
		return result;
	}

	/**
	 * 得到节点文本内容
	 */
	public static String getTextContent(Element e) {
		Text t = (Text) findElementContext(e).getFirst();
		return t.getData();
	}

	/**
	 * 得到所有 有某个属性得元素集合
	 */
	public static List findHasAttributeElems(String attrName, Element element) {
		List result = new LinkedList();
		if (!element.hasChildNodes()) {
			return result;
		}
		// 找有属性attrName得元素
		for (int i = 0; i < element.getChildNodes().getLength(); i++) {
			Node node = element.getChildNodes().item(i);
			if (node instanceof Element) {
				Element elem = (Element) node;
				if (elem.hasAttribute(attrName)) {
					result.add(elem);
				}
				result.addAll(findHasAttributeElems(attrName, elem));
			}
		}
		return result;
	}

	/**
	 * 根据属性名找元素
	 */
	public static List findElementsByAttribute(String attrName, String endTag,
			Element element) {
		List result = new LinkedList();
		NodeList list = element.getChildNodes();
		// 找有属性attrName得元素
		for (int i = 0; i < list.getLength(); i++) {
			Node node = list.item(i);
			if (node instanceof Element) {
				Element elem = (Element) node;
				if (elem.hasAttribute(endTag)) {
					continue;
				}
				if (elem.hasAttribute(attrName)) {
					result.add(elem);
				}
				result.addAll(findElementsByAttribute(attrName, endTag, elem));
			}
		}
		return result;
	}

	/**
	 * 得到参数元素最近的tag和参数tag一致的父元素
	 */
	public static Element getParentElement(Node elem, String tag) {
		if (elem.getParentNode() == null) {
			return null;
		}
		if (elem.getParentNode().getNodeType() == Node.ELEMENT_NODE) {
			Element e = (Element) elem.getParentNode();
			if (e.getTagName().equalsIgnoreCase(tag)) {
				return e;
			} else {
				return getParentElement(elem.getParentNode(), tag);
			}
		} else {
			return getParentElement(elem.getParentNode(), tag);
		}
	}

	/**
	 * 给元素添加一批子元素的拷贝
	 */
	public static void appendCopy(Element element, Collection elements) {
		// 挨个添加
		Iterator iter = elements.iterator();
		while (iter.hasNext()) {
			Element child = (Element) iter.next();
			Element e = (Element) child.cloneNode(true);
			element.appendChild(e);
		}
	}

	/**
	 * 给元素添加一批元素
	 */
	public static void append(Element element, Collection elements) {
		// 挨个添加
		Iterator iter = elements.iterator();
		while (iter.hasNext()) {
			Element child = (Element) iter.next();
			element.appendChild(child);
		}
	}

	/**
	 * 取得元素所有子的拷贝列表
	 */
	public static Collection getChildrenCopy(Element e) {
		Collection result = new LinkedList();
		// 对于每一个子
		NodeList nl = e.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			// 如果是元素，添加到结果中
			Node node = nl.item(i);
			if (node instanceof Element) {
				result.add(node.cloneNode(true));
			}
		}
		return result;
	}

	/**
	 * 取得一批元素的子拷贝
	 */
	public static Collection getCopy(Collection elements) {
		Collection result = new LinkedList();
		Iterator iter = elements.iterator();
		while (iter.hasNext()) {
			Element e = (Element) iter.next();
			Element copy = (Element) e.cloneNode(true);
			result.add(copy);
		}
		return result;
	}

	/**
	 * 获得元素的数字属性
	 */
	public static int getIntegerAttr(Element e, String attr, int init) {
		int result = init;
		String tmp = e.getAttribute(attr);
		if (tmp != null && !tmp.equals("")) {
			result = Integer.parseInt(tmp);
		}
		return result;
	}

	/**
	 * 删除标记元素
	 * 
	 * @param elements
	 */
	public static void removeElement(LinkedList elements) {
		for (int i = 0; i < elements.size(); i++) {
			// 删除带confirm,readonly标记的按钮
			Element e = (Element) elements.get(i);
			Element p = (Element) e.getParentNode();
			p.removeChild(e);
		}
	}
}